﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using MiniFox.Security;
using MiniFox.Utility;

namespace MiniFox.Infrastructure.Attributes
{
    /// <summary>
    /// 签名验证
    /// </summary>
    public class SignatureAttribute : ValidationAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        public SignatureAttribute()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="validationContext"></param>
        /// <returns></returns>
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            string val = value as string;
            if (string.IsNullOrWhiteSpace(val))
                return new ValidationResult(ErrorMessage);

            Type objType = validationContext.ObjectType;
            SortedList<int, string> signGroups = new SortedList<int, string>();

            foreach (PropertyInfo property in objType.GetProperties())
            {
                Attribute attr = GetCustomAttribute(property, typeof(SignatureGroupAttribute));
                if (attr == null)
                    continue;
                SignatureGroupAttribute signatureGroupAttr = attr as SignatureGroupAttribute;
                if (signatureGroupAttr == null)
                    continue;
                object propertyValue = property.GetValue(validationContext.ObjectInstance);
                if (property.PropertyType == typeof(DateTime))
                {
                    propertyValue = propertyValue.DateTimeFormat(GlobalStandardFormat.SEQ_SIMPLE_DATETIME_FORMAT); //string.Format("{0:yyyyMMddHHmmss}", propertyValue);
                }
                signGroups.Add(signatureGroupAttr.Ordinal, propertyValue.ToString().ToUpper());
            }
            if (signGroups.Count <= 0)
                return new ValidationResult(ErrorMessage);
            string signature = string.Empty;
            foreach (KeyValuePair<int, string> kvpair in signGroups)
            {
                signature += kvpair.Value;
            }
            signature = signature.MD5EncryptToHexString();
            bool valid = string.Equals(val, signature, StringComparison.OrdinalIgnoreCase);

            if (valid)
                return ValidationResult.Success;
            else
                return new ValidationResult(ErrorMessage);
        }
    }

    /// <summary>
    /// 签名组
    /// </summary>
    [AttributeUsage(AttributeTargets.Property)]
    public class SignatureGroupAttribute : Attribute
    {
        int _ordinal;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ordinal">签名顺序</param>
        public SignatureGroupAttribute(int ordinal)
        {
            _ordinal = ordinal;
        }
        /// <summary>
        /// 获取签名顺序
        /// </summary>
        public int Ordinal
        {
            get { return _ordinal; }
        }
    }
}
